<?php
namespace app\appin\validate;

use think\Validate;
use app\appin\service\Package as PS;

class AppinValidate extends Validate
{
    protected $rule = [
        'name' => 'require|checkName:name',
        'controller' => 'require|checkController:controller',
        'action' => 'require|checkAction:action'
    ];

    protected $message = [
        'name.require' => '插件不存在',
        'name.checkName' => '插件异常',
        'controller.require' => '插件控制器不存在',
        'controller.checkController' => '插件控制器异常',
        'action.require' => '插件方法不存在',
        'action.checkAction' => '插件方法异常'
    ];

    /**
     * [checkName 检测插件名称]
     * @param  [type] $value [description]
     * @param  [type] $rule  [description]
     * @param  [type] $data  [description]
     * @return [type]        [description]
     */
    public function checkName($value, $rule, $data)
    {
        if ( false === ( $config = PS::load($value) ) ) {
            throw new \Exception('插件不存在或者尚未安装');
        }
        bind('appinConfig', function() use($config) {
            return $config;
        });
        return true;
    }

    /**
     * [checkController 检测控制器名]
     * @param  [type] $value [description]
     * @param  [type] $rule  [description]
     * @param  [type] $data  [description]
     * @return [type]        [description]
     */
    public function checkController($value, $rule, $data)
    {
        $appinClass = '\\appin\\'.strtolower($data['name']).'\\controller\\'.ucfirst($value);
        if (stripos($value, '.') !== false) {
            $valueArr = explode( '.', $value);
            $appinClass = '\\appin\\'.strtolower($data['name']).'\\controller\\'.$valueArr[0].'\\'.ucfirst($valueArr[1]);
        }
        bind('appin_controller_classed', $appinClass);
        if ( !class_exists($appinClass) ) {
            throw new \Exception('插件控制器'.$value.'不存在');
        }
        return true;
    }

    /**
     * [checkAction 插件方法检测]
     * @param  [type] $value [description]
     * @param  [type] $rule  [description]
     * @param  [type] $data  [description]
     * @return [type]        [description]
     */
    public function checkAction($value, $rule, $data)
    {
        $appinClass = app()->appin_controller_classed;
        $appinReflectionClass = new \ReflectionClass($appinClass);
        if ( !$appinReflectionClass->hasMethod($value) ) {
            throw new \Exception('插件方法不存在'.$value);
        }
        $appinClassObject = $appinReflectionClass->getMethod($value);
        if ( !$appinClassObject->isPublic() ) {
            throw new \Exception('插件方法不存在'.$value);
        }
        return true;
    }
}
